package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.common.constants.message.NewsAutoScanConstants;
import com.heima.common.constants.message.WmNewsMessageConstants;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.dtos.NewsAuthDto;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.pojos.WmMaterial;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmNewsMaterial;
import com.heima.model.wemedia.vo.WmNewsVo;
import com.heima.utils.common.WmUserThreadLocal;
import com.heima.wemedia.mapper.WmMaterialMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmNewsMaterialMapper;
import com.heima.wemedia.service.WmNewsService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    @Value("${fdfs.url}")
    private String fdfsUrl;

    /**
     * 分页带条件查询自媒体文章列表
     *
     * @param wmNewsPageReqDto
     * @return
     */
    @Override
    public ResponseResult findAll(WmNewsPageReqDto wmNewsPageReqDto) {

        //查看是否携带参数
        if (null == wmNewsPageReqDto) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        //构建分页对象
        Page<WmNews> page = new Page<>(wmNewsPageReqDto.getPage(), wmNewsPageReqDto.getSize());

        //构建查询对象
        LambdaQueryWrapper<WmNews> wrapper = Wrappers.lambdaQuery();

        //添加当前用户条件
        wrapper.eq(WmNews::getUserId, WmUserThreadLocal.getUserId());

        //添加状态条件
        if (null != wmNewsPageReqDto.getStatus()) {
            wrapper.eq(WmNews::getStatus, wmNewsPageReqDto.getStatus());
        }

        //添加所属频道条件
        if (null != wmNewsPageReqDto.getChannelId()) {
            wrapper.eq(WmNews::getChannelId, wmNewsPageReqDto.getChannelId());
        }

        //根据关键字模糊查询
        if (null != wmNewsPageReqDto.getKeyword()) {
            wrapper.like(WmNews::getTitle, wmNewsPageReqDto.getKeyword());
        }

        //根据时间范围查询
        if (null != wmNewsPageReqDto.getBeginPubDate() && null != wmNewsPageReqDto.getEndPubDate()) {
            wrapper.between(WmNews::getCreatedTime, wmNewsPageReqDto.getBeginPubDate(), wmNewsPageReqDto.getEndPubDate());
        }

        //根据时间排序
        wrapper.orderByDesc(WmNews::getCreatedTime);

        //分页查询媒体文章
        IPage<WmNews> iPage = page(page, wrapper);

        //响应数据
        PageResponseResult result = new PageResponseResult(wmNewsPageReqDto.getPage(), wmNewsPageReqDto.getSize(), (int) iPage.getTotal());
        result.setData(iPage.getRecords());
//        result.setHost(fdfsUrl);
        return result;
    }

    @Autowired
    private KafkaTemplate kafkaTemplate;

    /**
     * 提交文章
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult summitNews(WmNewsDto dto) {

        //查看是否携带参数
        if (null == dto) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        //修改自动封面为null
        if (dto.getType() == WmNews.WM_NEWS_TYPE_AUTO) {
            dto.setType(null);
        }

        //将dto的数据传输到实体类中
        WmNews wmNews = new WmNews();
        BeanUtils.copyProperties(dto, wmNews); //TODO

        //处理封面图片
        if (null != dto.getImages()) {
            wmNews.setImages(dto.getImages().toString().replace("[", "")
                    .replace("]", "").replace(" ", ""));
        }

        //增加修改时间
        wmNews.setSubmitedTime(new Date());

        //存入作者
        wmNews.setUserId(WmUserThreadLocal.getUserId());

        //判断是否为修改文章
        if (null != dto.getId()) {

            //删除跟该文章的所有素材关联
            deltteNewsMaterial(dto.getId());

            //修改用户
            updateById(wmNews);
        } else {

            //增加提交时间
            wmNews.setCreatedTime(new Date());

            //新增用户
            save(wmNews);
        }

        //草稿不需要经行素材关联直接返回
        if (dto.getStatus() == 0) {
            return ResponseResult.okResult(wmNews);
        }

        //添加图文内容中的素材关联
        List<String> materialIdList = saveContentNewsMaterial(wmNews.getContent(), wmNews.getId());

        //添加封面图片中的素材关联
        List<String> material = saveImagesNewsMaterial(dto, materialIdList, wmNews.getId());

        //为自动封面添加固定封面
        if (null == dto.getType() && material != null && material.size() > 0) {

            //修改封面信息
            wmNews.setImages(material.toString().replace("[", "")
                    .replace("]", "").replace(" ", ""));
            updateById(wmNews);
        }

        //如果是保存提交审核
        if (wmNews.getStatus() == WmNews.WM_COVER_REFERENCE) {
            kafkaTemplate.send(NewsAutoScanConstants.WM_NEWS_AUTO_SCAN_TOPIC, JSON.toJSONString(wmNews.getId()));
        }

        return ResponseResult.okResult(fdfsUrl);
    }

    /**
     * 根据id获取文章信息
     *
     * @return
     */
    @Override
    public ResponseResult findWmNewsById(Integer newsId) {

        //检查参数
        if (null == newsId) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        //获取参数
        WmNews wmNews = getById(newsId);

        //响应参数
        if (null == wmNews) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        return ResponseResult.okResult(wmNews);
    }

    /**
     * 删除文章
     *
     * @return
     */
    @Override
    public ResponseResult delNews(Integer newsId) {

        //检查参数
        if (null == newsId) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        //获取文章信息 查询是否上架
        WmNews wmNews = getById(newsId);
        if (wmNews == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        //判断是否上架
        if (wmNews.getStatus() == WmNews.WM_FA_BU_REFERENCE && wmNews.getEnable() == 1) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NO_OPERATOR_AUTH, "文章已上架，请先下架后删除");
        }

        //删除素材关联
        deltteNewsMaterial(newsId);

        //非上架状态可以删除
        boolean remove = removeById(newsId);

        //判断是否删除成功
        if (remove) {
            return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
        }

        return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
    }

    /**
     * 上下架
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult downOrUp(WmNewsDto dto) {

        //检查参数
        if (null == dto && null == dto.getEnable()) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        //获取文章
        WmNews wmNews = getById(dto.getId());
        if (null == wmNews) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        //判断文章是否审核完成
        if (wmNews.getStatus() != WmNews.WM_FA_BU_REFERENCE) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NO_OPERATOR_AUTH, "文章还未审核，请审核通过后重试");
        }

        //异步发送信息同步数据
        if (null != wmNews.getArticleId()) {
            Map<String, Object> map = new HashMap<>();
            map.put("enable", dto.getEnable());
            map.put("articleId", wmNews.getArticleId());

            //发送异步信息
            kafkaTemplate.send(WmNewsMessageConstants.WM_NEWS_UP_OR_DOWN_TOPIC, JSON.toJSONString(map));
        }

        //修改上下架数据
        wmNews.setEnable(dto.getEnable());
        updateById(wmNews);

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 查询需要发布的文章id列表
     *
     * @return
     */
    @Override
    public List<Integer> findRelease() {
        LambdaQueryWrapper<WmNews> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(WmNews::getStatus, 4).or().eq(WmNews::getStatus, 8).lt(WmNews::getPublishTime, new Date());
        List<WmNews> list = list(wrapper);
        return list.stream().map(WmNews::getId).collect(Collectors.toList());
    }

    @Autowired
    private WmNewsMapper wmNewsMapper;

    /**
     * 查询文章列表
     *
     * @param dto
     * @return
     */
    @Override
    public PageResponseResult findList(NewsAuthDto dto) {

        //转换计算分页
        dto.setPage((dto.getPage() - 1) * dto.getSize());

        //模糊查询拼接
        if (null != dto.getTitle() && !dto.getTitle().equals("")) {
            dto.setTitle("%" + dto.getTitle() + "%");
        }

        //查询参数
        if (null == dto.getStatus()) {
            dto.setStatus((short) 3);
        }

        //查询数据
        List<WmNewsVo> list = wmNewsMapper.findListAndPage(dto);
        int count = wmNewsMapper.findListCount(dto);

        //响应结果
        PageResponseResult result = new PageResponseResult(dto.getPage(), dto.getSize(), count);
        result.setData(list);

        return result;
    }

    /**
     * 查询文章详情
     *
     * @param id
     * @return
     */
    @Override
    public WmNewsVo findWmNewsVo(Integer id) {

        return wmNewsMapper.findWmNewsVo(id);
    }


    @Autowired
    private WmNewsMaterialMapper wmNewsMaterialMapper;

    @Autowired
    private WmMaterialMapper wmMaterialMapper;

    /**
     * 添加封面图片中的素材关联
     *
     * @param dto
     * @param materialIdList
     */
    private List<String> saveImagesNewsMaterial(WmNewsDto dto, List<String> materialIdList, Integer newsId) {

        //获取url
        List<String> imagesList = dto.getImages();

        //判断是无图还是自动
        if (null == dto.getType()) {

            //自动配图
            if (materialIdList.size() == 0) {

                //内容中无图片直接返回
                return null;
            } else if (materialIdList.size() <= 2) {

                //内容中图片少于3张默认获取第一张
                imagesList.add(materialIdList.get(0));
            } else {

                //内容中图片数量大于3张默认获取前3张
                imagesList.add(materialIdList.get(0));
                imagesList.add(materialIdList.get(1));
                imagesList.add(materialIdList.get(2));
            }
        } else if (dto.getType() == WmNews.WM_NEWS_NONE_IMAGE) {

            //无图直接返回
            return imagesList;
        }

        //添加素材关联
        saveNewsMaterial(imagesList, newsId, WmNewsMaterial.WM_TYPE_ZHU_TU);

        //为自动封面添加固定封面
        return imagesList;
    }

    /**
     * 添加内容中的图文素材关联
     *
     * @param content
     * @return
     */
    private List<String> saveContentNewsMaterial(String content, Integer newsId) {

        //将图文内容转换成json数据
        ArrayList<Map> listMap = JSON.parseObject(content, ArrayList.class);

        //取出所有图片
        ArrayList<String> urlList = new ArrayList<>();
        for (Map map : listMap) {
            if (map.get("type").equals("image")) {
                urlList.add(String.valueOf(map.get("value")));
            }
        }

        //判断文章中是否有图片
        if (urlList.size() == 0) {
            return urlList;
        }

        //添加素材关联
        saveNewsMaterial(urlList, newsId, WmNewsMaterial.WM_TYPE_NEI_RONG);

        return urlList;
    }

    /**
     * 添加素材关联
     *
     * @param urlList
     * @return
     */
    private void saveNewsMaterial(List<String> urlList, Integer newsId, Short type) {

        //查询所有图片id
        LambdaQueryWrapper<WmMaterial> wrapperWmMaterial = Wrappers.lambdaQuery();
        wrapperWmMaterial.in(WmMaterial::getUrl, urlList);
        List<WmMaterial> wmMaterials = wmMaterialMapper.selectList(wrapperWmMaterial);

        //获取所有图片的id
        ArrayList<String> idList = new ArrayList<>();
        for (WmMaterial wmMaterial : wmMaterials) {
            for (String url : urlList) {
                if (wmMaterial.getUrl().equals(url)) {
                    idList.add(wmMaterial.getId().toString());
                    break;
                }
            }
        }

        //保存素材关联
        wmNewsMaterialMapper.saveRelationsByContent(idList, newsId, type);
    }

    /**
     * 删除跟该文章的所有素材关联
     *
     * @param newsId
     */
    private void deltteNewsMaterial(Integer newsId) {
        LambdaQueryWrapper<WmNewsMaterial> wrapper = Wrappers.<WmNewsMaterial>lambdaQuery();
        wrapper.eq(WmNewsMaterial::getNewsId, newsId);
        wmNewsMaterialMapper.delete(wrapper);
    }
}
